package com.keier.fragment.demo.util;


import android.os.Build;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.View.MeasureSpec;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.view.animation.Animation.AnimationListener;
import android.widget.ListView;

/**
 * 回归操作类
 * @author keier
 *
 */
public class ReTurnOperator {
	
	private ListView mListView;
	private View mReturnView;
	private int mQuickReturnHeight;
	private int mItemCount;
	private int mItemOffsetY[];
	private boolean scrollIsComputed = false;
	private int mHeight;
	
	private FooterReturn mFooterReturn;
	private HeaderReturn mHeaderReturn;
	
	
	public enum ReturnType{
		RETURN_FOOTER(0),
		RETURN_HEADER(1);
		
		private int type;
		
		private ReturnType(int type){
			this.type = type;
		}
	}
	
	/**
	 * 初始化有底部回归view的操作类
	 * @param listView
	 * @param returnView 有回归动画的view
	 */
	public ReTurnOperator(ListView listView, View returnView){
		this(listView, returnView, null);
	}
	
	/**
	 * 初始化有顶部回归view的操作类
	 * @param listView
	 * @param returnView  有回归动画的view
	 * @param placeView   站位view，位于ListView的header中
	 */
	public ReTurnOperator(ListView listView, View returnView, View placeView){
		mListView = listView;
		mReturnView = returnView;
		mListView.getViewTreeObserver().addOnGlobalLayoutListener(
				new ViewTreeObserver.OnGlobalLayoutListener() {
					@Override
					public void onGlobalLayout() {
						mQuickReturnHeight = mReturnView.getHeight();
						computeScrollY();
					}
				});
		if(placeView == null){
			mFooterReturn = new FooterReturn();
		}else{
			mHeaderReturn = new HeaderReturn(placeView);
		}
	}
	
	private int getListHeight() {
		return mHeight;
	}

	private void computeScrollY() {
		mHeight = 0;
		mItemCount = mListView.getAdapter().getCount();
		if (mItemOffsetY == null) {
			mItemOffsetY = new int[mItemCount];
		}
		for (int i = 0; i < mItemCount; ++i) {
			View view = mListView.getAdapter().getView(i, null, mListView);
			view.measure(
					MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
					MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
			mItemOffsetY[i] = mHeight;
			mHeight += view.getMeasuredHeight();
			System.out.println(mHeight);
		}
		scrollIsComputed = true;
	}

	private boolean scrollYIsComputed() {
		return scrollIsComputed;
	}

	private int getComputedScrollY() {
		int pos, nScrollY, nItemY;
		View view = null;
		pos = mListView.getFirstVisiblePosition();
		view = mListView.getChildAt(0);
		nItemY = view.getTop();
		nScrollY = mItemOffsetY[pos] - nItemY;
		return nScrollY;
	}
	
	public void reTurnOperate(ReturnType type){
		switch (type) {
		case RETURN_FOOTER:
			mFooterReturn.returnView();
			break;

		case RETURN_HEADER:
			mHeaderReturn.returnView();
			break;
		}
	}
	
	private class FooterReturn{

		private static final int STATE_ONSCREEN = 0;
		private static final int STATE_OFFSCREEN = 1;
		private static final int STATE_RETURNING = 2;
		private int mState = STATE_ONSCREEN;
		private int mScrollY;
		private int mMinRawY = 0;
		
		private TranslateAnimation anim;
		
		/** 底部回归动画*/
		private void returnView(){
			mScrollY = 0;
			int translationY = 0;

			if (scrollYIsComputed()) {
				mScrollY = getComputedScrollY();
			}

			int rawY = mScrollY;

			switch (mState) {
			case STATE_OFFSCREEN:
				if (rawY >= mMinRawY) {
					mMinRawY = rawY;
				} else {
					mState = STATE_RETURNING;
				}
				translationY = rawY;
				break;

			case STATE_ONSCREEN:
				if (rawY > mQuickReturnHeight) {
					mState = STATE_OFFSCREEN;
					mMinRawY = rawY;
				}
				translationY = rawY;
				break;

			case STATE_RETURNING:

				translationY = (rawY - mMinRawY) + mQuickReturnHeight;

				if (translationY < 0) {
					translationY = 0;
					mMinRawY = rawY + mQuickReturnHeight;
				}

				if (rawY == 0) {
					mState = STATE_ONSCREEN;
					translationY = 0;
				}

				if (translationY > mQuickReturnHeight) {
					mState = STATE_OFFSCREEN;
					mMinRawY = rawY;
				}
				break;
			}

			/** this can be used if the build is below honeycomb **/
			if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB) {
				anim = new TranslateAnimation(0, 0, translationY,
						translationY);
				anim.setFillAfter(true);
				anim.setDuration(0);
				mReturnView.startAnimation(anim);
			} else {
				mReturnView.setTranslationY(translationY);
			}
		}
	}
	
	private class HeaderReturn{
		private int mCachedVerticalScrollRange;
		private int mQuickReturnHeight;

		private static final int STATE_ONSCREEN = 0;
		private static final int STATE_OFFSCREEN = 1;
		private static final int STATE_RETURNING = 2;
		private static final int STATE_EXPANDED = 3;
		private int mState = STATE_ONSCREEN;
		private int mScrollY;
		private int mMinRawY = 0;
		private int rawY;
		private boolean noAnimation = false;

		private TranslateAnimation anim;
		
		private View placeView;
		
		public HeaderReturn(View placeView){
			this.placeView = placeView;
		}
		
		public void returnView(){
			mScrollY = 0;
			int translationY = 0;

			if (scrollYIsComputed()) {
				mScrollY = getComputedScrollY();
			}

			rawY = placeView.getTop()
					- Math.min(
							mCachedVerticalScrollRange
									- mListView.getHeight(), mScrollY);

			switch (mState) {
			case STATE_OFFSCREEN:
				if (rawY <= mMinRawY) {
					mMinRawY = rawY;
				} else {
					mState = STATE_RETURNING;
				}
				translationY = rawY;
				break;

			case STATE_ONSCREEN:
				if (rawY < -mQuickReturnHeight) {
					System.out.println("test3");
					mState = STATE_OFFSCREEN;
					mMinRawY = rawY;
				}
				translationY = rawY;
				break;

			case STATE_RETURNING:

				if (translationY > 0) {
					translationY = 0;
					mMinRawY = rawY - mQuickReturnHeight;
				}

				else if (rawY > 0) {
					mState = STATE_ONSCREEN;
					translationY = rawY;
				}

				else if (translationY < -mQuickReturnHeight) {
					mState = STATE_OFFSCREEN;
					mMinRawY = rawY;

				} else if (mReturnView.getTranslationY() != 0
						&& !noAnimation) {
					noAnimation = true;
					anim = new TranslateAnimation(0, 0,
							-mQuickReturnHeight, 0);
					anim.setFillAfter(true);
					anim.setDuration(250);
					mReturnView.startAnimation(anim);
					anim.setAnimationListener(new AnimationListener() {

						@Override
						public void onAnimationStart(Animation animation) {
							// TODO Auto-generated method stub

						}

						@Override
						public void onAnimationRepeat(Animation animation) {
							// TODO Auto-generated method stub

						}

						@Override
						public void onAnimationEnd(Animation animation) {
							noAnimation = false;
							mMinRawY = rawY;
							mState = STATE_EXPANDED;
						}
					});
				}
				break;

			case STATE_EXPANDED:
				if (rawY < mMinRawY - 2 && !noAnimation) {
					noAnimation = true;
					anim = new TranslateAnimation(0, 0, 0,
							-mQuickReturnHeight);
					anim.setFillAfter(true);
					anim.setDuration(250);
					anim.setAnimationListener(new AnimationListener() {

						@Override
						public void onAnimationStart(Animation animation) {
						}

						@Override
						public void onAnimationRepeat(Animation animation) {

						}

						@Override
						public void onAnimationEnd(Animation animation) {
							noAnimation = false;
							mState = STATE_OFFSCREEN;
						}
					});
					mReturnView.startAnimation(anim);
				} else if (translationY > 0) {
					translationY = 0;
					mMinRawY = rawY - mQuickReturnHeight;
				}

				else if (rawY > 0) {
					mState = STATE_ONSCREEN;
					translationY = rawY;
				}

				else if (translationY < -mQuickReturnHeight) {
					mState = STATE_OFFSCREEN;
					mMinRawY = rawY;
				} else {
					mMinRawY = rawY;
				}
			}
			/** this can be used if the build is below honeycomb **/
			if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB) {
				anim = new TranslateAnimation(0, 0, translationY,
						translationY);
				anim.setFillAfter(true);
				anim.setDuration(0);
				mReturnView.startAnimation(anim);
			} else {
				mReturnView.setTranslationY(translationY);
			}

		}
	}
	
	
}
